grammar GrammarBackup;

options {
  language = Java;
}

@header {
package com.plt.w2w;
import java.util.Map;
import java.util.HashMap;
import java.io.*;
import java.util.ArrayList;
}

@lexer::header {
package com.plt.w2w;
}

@members {
	public Map<String, String[]> symbolTable = new HashMap<String, String[]>();
	public ArrayList<String> mainFuncString = new ArrayList<String>();
	public ArrayList<Garment> garments = new ArrayList<Garment>();
}

start
  :
  wardrobeCreation
    {
      //call the java class handling wardrobe creation
      Wardrobe obj = new Wardrobe();
      obj.create(garments,$wardrobeCreation.name);
//      for(int i=0; i<garments.size(); i++)
//      {
//        garments.get(i).printNicely();
//      }
    }
  | mainProgram
    {
//      for(int i=0; i<mainFuncString.size(); i++)
//      {
//        System.out.println(mainFuncString.get(i));
//      }
//      
      MainFuncBackEnd obj = new MainFuncBackEnd(symbolTable,mainFuncString);
      obj.backEnd();
      //call class handling
    }
  ;

wardrobeCreation returns [String name] 
  :
  createStatement items 
  {
      $name = $createStatement.name;
  }
  ;

createStatement returns [String name] 
  :
  CREATET WARDROBET wardrobeName ENDOFSTMT ENDOFLINE 
  {
      $name = $wardrobeName.text;
  }
  ;

items
  :
  item ENDOFLINE items1
  {
    garments.add($item.garm);
  }
  ;

items1
  :
  item ENDOFLINE items1
  {
    garments.add($item.garm);
  }
  |
  ;

item returns [Garment garm]
  :
  LEFTCURLY ENDOFLINE type category weight color shade maker preference RIGHTCURLY
  {
    Garment g = new Garment($type.val, $weight.val, $maker.val, $color.val, $shade.val, $preference.val);
    $garm = g;
  }
  ;

type returns [String val]
  :
  ITEMT ASSIGNMENT_OP value ENDOFSTMT ENDOFLINE
  {
    $val = $value.text;
  }
  ;
  
category returns [String val]
  :
  ITEMT ASSIGNMENT_OP value ENDOFSTMT ENDOFLINE
  {
    $val = $value.text;
  }
  ;
  
weight returns [String val]
  :
  WEIGHT ASSIGNMENT_OP value ENDOFSTMT ENDOFLINE
  {
    $val = $value.text;
  }
  ;
  
color returns [String val]
  :
  COLORT ASSIGNMENT_OP value ENDOFSTMT ENDOFLINE
  {
    $val = $value.text;
  }
  |
  {
    $val = "";
  }
  ;

shade returns [String val]
  :
  SHADET ASSIGNMENT_OP value ENDOFSTMT ENDOFLINE
  {
    $val = $value.text;
  }
  |
  {
    $val = "";
  }
  ;

maker returns [String val]
  :
  MAKERT ASSIGNMENT_OP value ENDOFSTMT ENDOFLINE
  {
    $val = $value.text;
  }
  |
  {
    $val = "";
  }
  ;

preference returns [String val]
  :
  PREFERENCET ASSIGNMENT_OP prefRange ENDOFSTMT ENDOFLINE
  {
    $val = $prefRange.text;
  }
  |
  {
    $val = "2";
  }
  ;

mainProgram
  :
  header mainDecl block createEventCommand runCommand
  ;

header
  :
  USET WARDROBET wardrobeNames ENDOFSTMT ENDOFLINE
  |
  ;

wardrobeNames returns [String value]
  :
  wardrobeName wardrobeNames1
    {
//       System.out.println("text2: "+$wardrobeName.text);
       $value = $wardrobeName.text + ", " + $wardrobeNames1.value ;
       $value = $value.substring(0, $value.length()-2);
    }
  ;

wardrobeNames1 returns [String value]
  :
  '+' wardrobeName w1=wardrobeNames1
  {
//      System.out.println("text: "+$wardrobeName.text);
       $value = $wardrobeName.text + ", " + $w1.value;
   }
  | //null
  { $value = "";}
  ;

mainDecl
  :
  VOID MAIN LEFTPARAN RIGHTPARAN ENDOFLINE
  ;

block
  :
  LEFTCURLY ENDOFLINE lines RIGHTCURLY ENDOFLINE
  ;

lines
  :
  line ENDOFLINE lines1
  ;

lines1
  :
  line ENDOFLINE lines1
  |
  ;

line
  :
  block
  | assignmentStatement
  //        | fOREACH dataType variableName ':' wardrobeName
  | INCLUDE variableName ENDOFSTMT
  | REJTOK variableName ENDOFSTMT
  | RETTOK IDENTIFIER
  |
  ;

assignmentStatement
  :
  DATET variableName ASSIGNMENT_OP DATE ENDOFSTMT
  {
    if(!symbolTable.containsKey($variableName.text)){
    String[] s = new String[2];
    s[0] = "date";
    s[1] = $DATE.text;
    symbolTable.put($variableName.text, s);}
    else
      System.out.println("Error! You are trying to redifine a previously defined variable " + $variableName.text);
  }
  | ENDDATE variableName ASSIGNMENT_OP DATE ENDOFSTMT
  {
    if(!symbolTable.containsKey($variableName.text)){
    String[] s = new String[2];
    s[0] = "enddate";
    s[1] = $DATE.text;
    symbolTable.put($variableName.text, s);
    }
    else
      System.out.println("Error! You are trying to redifine a previously defined variable " + $variableName.text);
  }
  | ENDTIME variableName ASSIGNMENT_OP TIME ENDOFSTMT
  {
    if(!symbolTable.containsKey($variableName.text)){
    String[] s = new String[2];
    s[0] = "endtime";
    s[1] = $TIME.text;
    symbolTable.put($variableName.text, s);}
    else
      System.out.println("Error! You are trying to redifine a previously defined variable " + $variableName.text);
  }
  | INT variableName ASSIGNMENT_OP NUMBER ENDOFSTMT
  {
    if(!symbolTable.containsKey($variableName.text)){
    String[] s = new String[2];
    s[0] = "int";
    s[1] = $NUMBER.text;
    symbolTable.put($variableName.text, s);}
    else
      System.out.println("Error! You are trying to redifine a previously defined variable " + $variableName.text);
  }
  | STARTDATE variableName ASSIGNMENT_OP DATE ENDOFSTMT
  {
    if(!symbolTable.containsKey($variableName.text)){
    String[] s = new String[2];
    s[0] = "startdate";
    s[1] = $DATE.text;
    symbolTable.put($variableName.text, s);}
    else
      System.out.println("Error! You are trying to redifine a previously defined variable " + $variableName.text);
  }
  | STARTTIME variableName ASSIGNMENT_OP TIME ENDOFSTMT
  {
    if(!symbolTable.containsKey($variableName.text)){
    String[] s = new String[2];
    s[0] = "starttime";
    s[1] = $TIME.text;
    symbolTable.put($variableName.text, s);}
    else
      System.out.println("Error! You are trying to redifine a previously defined variable " + $variableName.text);
  }
  | STRING variableName ASSIGNMENT_OP IDENTIFIER ENDOFSTMT
  {
    if(!symbolTable.containsKey($variableName.text)){
    String[] s = new String[2];
    s[0] = "string";
    s[1] = $IDENTIFIER.text;
    symbolTable.put($variableName.text, s);}
    else
      System.out.println("Error! You are trying to redifine a previously defined variable " + $variableName.text);
  }
  | TIMET variableName ASSIGNMENT_OP TIME ENDOFSTMT
  {
    if(!symbolTable.containsKey($variableName.text)){
    String[] s = new String[2];
    s[0] = "time";
    s[1] = $TIME.text;
    symbolTable.put($variableName.text, s);}
    else
      System.out.println("Error! You are trying to redifine a previously defined variable " + $variableName.text);
  }
  ;

createEventCommand
  :
  CREATEEVENT LEFTPARAN parameters RIGHTPARAN ENDOFSTMT ENDOFLINE
  {
    String s = new String("createEvent(" + $parameters.value + ")");
    mainFuncString.add(s);
    
  }
  ;

runCommand
  :
  GENERATEOUTFIT LEFTPARAN parameters RIGHTPARAN ENDOFSTMT
  {
    String s = new String("generateOutfit(" + $parameters.value + ")");
    mainFuncString.add(s);
  }
  ;

parameters  returns [String value]
  :
  IDENTIFIER parameters1
    {
//       System.out.println("text2: "+$IDENTIFIER.text);
       $value = $IDENTIFIER.text + ", " + $parameters1.param ;
       $value = $value.substring(0, $value.length()-2);
    }
  ;

parameters1 returns [String param]
  :
  ',' IDENTIFIER p1=parameters1
    {
//      System.out.println("text: "+$IDENTIFIER.text);
        $param = $IDENTIFIER.text + ", " + $p1.param;
    }
  |//null
  { 
    $param = "";
//    System.out.println ("i did come here"); 
  }
  ;

wardrobeName
  :
  IDENTIFIER
  ;

prefRange
  :
  '1' | '2' | '3'
  ;

value
  :
  IDENTIFIER
  ;

variableName
  :
  IDENTIFIER
  ;

DATE
  :
  ('0'| '1')('0'..'9') ('\/') ('0'..'3') ('0'..'9')
  ;

TIME
  :
  ('0'..'2') ('0'..'9') (':') ('0'..'5') ('0'..'9')
  ;

CREATET
  :
  'create'
  ;

ITEMT
  :
  'item'
  ;

CATEGORY
  :
   'category'
   ;

WEIGHT
  :
  'weight'
  ;

COLORT
  :
  'color'
  ;

SHADET
  :
  'shade'
  ;

MAKERT
  :
  'maker'
  ;

PREFERENCET
  :
  'preference'
  ;

WARDROBET
  :
  'wardrobe'
  ;

USER
  :
  'user'
  ;

AGE
  :
  'age'
  ;

OCCUPATION
  :
  'occupation'
  ;

USET
  :
  'use'
  ;

IF
  :
  'if'
  ;

ELSE
  :
  'else'
  ;

VOID
  :
  'void'
  ;

MAIN
  :
  'main'
  ;

FOREACH
  :
  'for each'
  ;

AND
  :
  'and'
  ;

OR
  :
  'or'
  ;

CREATEEVENT
  :
  'createEvent'
  ;

GENERATEOUTFIT
  :
  'generateOutfit'
  ;

INCLUDE
  :
  'include'
  ;

REJTOK
  :
  'rejtok'
  ;

RETTOK
  :
  'return'
  ;

DATET
  :
  'date'
  ;

ENDDATE
  :
  'endDate'
  ;

ENDTIME
  :
  'endTime'
  ;

EVENT
  :
  'event'
  ;

GARMENT
  :
  'garment'
  ;

HUMIDITY
  :
  'humidity'
  ;

INT
  :
  'int'
  ;

STARTDATE
  :
  'startDate'
  ;

STARTTIME
  :
  'startTime'
  ;

STRING
  :
  'string'
  ;

TEMPERATURE
  :
  'temperature'
  ;

TIMET
  :
  'time'
  ;

WEATHER
  :
  'weather'
  ;

LEFTPARAN
  :
  '('
  ;

RIGHTPARAN
  :
  ')'
  ;

LEFTCURLY
  :
  '{'
  ;

RIGHTCURLY
  :
  '}'
  ;

ASSIGNMENT_OP
  :
  '='
  ;

CONDITIONAL_OP
  :
  ('=='| '!=' | '<' | '>' | '<=' | '>=' )
  ;

IDENTIFIER
  :
  ('a'..'z'| 'A'..'Z')('a'..'z'| 'A'..'Z'| '0'..'9')*
  ;

NUMBER
  :
  ('0'..'9')+
  ;

ENDOFSTMT
  :
  ';'
  ;

ENDOFLINE
  :
  '\n'
  ;

DELIMITER
  :
  '.'
  ;
  
 WS : (' ' | '\t' | '\n' | '\r' | '\f ')+ {$channel=HIDDEN;};